﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Reflection;
using System.Xml;

namespace Xom.Elements
{
    public abstract class XomElement : IXomElement, IDisposable
    {
        protected bool disposed = false;

        /// <summary>
        /// XmlNode that contains the root informations
        /// </summary>
        public IXomNode RootNode { get; set; }

        /// <summary>
        /// List of all property informations
        /// </summary>
        public IDictionary<string, IXomPropertyInfo> Properties { get; set; }

        /// <summary>
        /// Wrap Event for all CollectionChangedEvents
        /// </summary>
        public event NotifyXomCollectionChangedEventHandler XomCollectionChanged;

        /// <summary>
        /// Event Handler for Property Changed
        /// </summary>
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Raised Event
        /// </summary>
        /// <param name="propertyName">Name of the Property</param>
        protected void RaisePropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler propertyChanged = PropertyChanged;
            if ((propertyChanged != null))
            {
                propertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        /// <summary>
        /// Raised XomCollectionChanged Event
        /// </summary>
        /// <param name="sender">Parent of the Property</param>
        /// <param name="propertyName">Name of the Collection</param>
        /// <param name="notifyCollectionChangedEventArgs">ChangedEventArguments</param>
        protected void RaiseXomCollectionChanged(IXomElement sender, string propertyName, NotifyCollectionChangedEventArgs notifyCollectionChangedEventArgs)
        {
            if ((XomCollectionChanged != null))
            {
                XomCollectionChanged(sender, propertyName, notifyCollectionChangedEventArgs);
            }
        }

        protected XomElement()
        {
            Properties = new Dictionary<string, IXomPropertyInfo>();
        }

        /// <summary>
        /// Dispose() calls Dispose(true)
        /// </summary>
        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        /// <summary>
        /// NOTE: Leave out the finalizer altogether if this class doesn't 
        /// own unmanaged resources itself, but leave the other methods
        /// exactly as they are.
        /// </summary>
        ~XomElement()
        {
            // Finalizer calls Dispose(false)
            Dispose(false);
        }

        /// <summary>
        ///  Clean-up code for IDisposable
        /// </summary>
        /// <param name="disposing">If true only managed Code</param>
        protected virtual void Dispose(bool disposing)
        {
            if (!disposed)
            {
                if (disposing)
                {
                    // Free other state (managed objects).
                }

                disposed = true;
            }
        }
    }


    public class XomPropertyInfo<T>: IXomPropertyInfo<T>
    {
        public PropertyInfo Info { get; set; }

        public IXomNode<T> Node { get; set; }

        public XomPropertyInfo(PropertyInfo info, IXomNode<T> node)
        {
            Info = info;
            Node = node;
        }
    }

    public class XomNode<T> : IXomNode<T>
    {
        /// <summary>
        /// Represents a single node in the XML document.
        /// </summary>
        public T Value { get; set; }

        /// <summary>
        /// Ctor
        /// </summary>
        /// <param name="value"></param>
        public XomNode(T value)
        {
            Value = value;
        }
    }
}
